#include "libcomm.h"

CommonRef::CommonRef(void* ptr) :m_ptr(ptr), m_ref_count(1){}
CommonRef::~CommonRef() {}
void* CommonRef::ptr() { return m_ptr; }
int CommonRef::Release(bool delptr)
{
	int refCount = --m_ref_count;
	MYLIB_ASSERT(refCount >= 0);
	if (0 == refCount)
	{
		if(delptr)
			this->DeletePtr();
		delete this;
	}
	return refCount;
}

int CommonRef::AddRef()
{
	return ++m_ref_count;
}


////////////////////////////////////////////////////////////////////////// SharedPtrImp


SharedPtrImp::SharedPtrImp(CommonRef* ref)
	: m_ref(ref)
{
}

SharedPtrImp::~SharedPtrImp()
{
	Release();
}

void SharedPtrImp::Release()
{
	if(NULL != m_ref)
	{
		m_ref->Release();
		m_ref = NULL;
	}
}

SharedPtrImp::SharedPtrImp(const SharedPtrImp& rhs)
	:m_ref(rhs.m_ref)
{
	if (NULL != m_ref)
		m_ref->AddRef();
}

SharedPtrImp& SharedPtrImp::operator=(const SharedPtrImp& rhs)
{
	if(m_ref != rhs.m_ref)
	{
		this->Release();
		if(NULL != rhs.m_ref)
		{
			rhs.m_ref->AddRef();
			m_ref = rhs.m_ref;
		}
	}
	return *this;
}

void* SharedPtrImp::ptr() const
{
	return ((NULL == m_ref) ? NULL : m_ref->ptr());
}

////////////////////////////////////////////////////////////////////////// ScopedPtrImp

ScopedPtrImp::ScopedPtrImp(CommonRef* ref):m_ref(ref)
{
}

ScopedPtrImp::~ScopedPtrImp()
{
	Release();
}

void ScopedPtrImp::Release()
{
	if (NULL != m_ref)
	{
		m_ref->Release();
		m_ref = NULL;
	}
}

void* ScopedPtrImp::ptr() const
{
	return ((NULL == m_ref) ? NULL : m_ref->ptr());
}

void* ScopedPtrImp::detach()
{
	void* ptr = NULL;
	if(NULL != m_ref)
	{
		ptr = m_ref->ptr();
		m_ref->Release(false);
		m_ref = NULL;
	}
	return ptr;
}

void ScopedPtrImp::attach(CommonRef* ref)
{
	if(m_ref != ref)
	{
		this->Release();
		m_ref = ref;
	}
}